/*
 *
 * Copyright (C) 2008 Ed Hong
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifndef SUBBANDITERATOR_H
#define SUBBANDITERATOR_H

#include "SubbandBits.h"
#include "Characteristics.h"
#include "contexttree.h"

typedef struct {
  sbploc loc;
  int context;
  int index; 
} CoeffHeapNode;

typedef struct {
  CoeffHeapNode **dat; // heap-array data structure for sorting coeffs. 
  // we will use minimizing heap; smallest heapnodes get encoded/decoded first. 
  // starts at index 1; index 0 left empty. 
  int (*IsLessthan)(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m);
  // lessthan ordering method between coeffs; NULL for standard ordering. 
  contexttree *ct; // contexttree used for context classification in ordering. 
  sbploc loc; // refers to current sbploc that needs to be coded
  int numComponents;
  SubbandComponent *sc;
  int totalcoeffs;
  QccENTArithmeticModel *model; // used by sorting algorithms.
} SubbandIterator;

// *si is already created; 
// allocates dat field based on sc size. 
// also resets neighbors_coded to 0's, and
// sets up locators, if necessary. 
 // if f is null, then use standard ordering.
//  c== NULL will exhibit same behavior as
//   a context with just one leaf node with 
//   context value 0. 
// if c==NULL, than no heap data or heapnodes will be
//   created (thus, no context updates). Also no
//   locators modified in this case. 
// if c!= NULL, heap nodes will be created, 
//   and contexts will be updated (even if they are
//    never used to determine ordering, as would be
//    the case when f ==NULL)

int SubbandIterator_InitAlloc(SubbandIterator *si, SubbandComponent *sc, 
				     int numComponents, 
				     int (*f)(const CoeffHeapNode *, 
					      const CoeffHeapNode *, 
					      const QccENTArithmeticModel *), 
			      contexttree *c, 
			      QccENTArithmeticModel *m
			      );

//returns  current bit that we need to encode/decode next
sbploc SubbandIterator_curr(SubbandIterator *si); 

// before this call, Coeffdat of current sbploc must be updated
//  to be accurate with respect to its current bitplane. (this
//  updating occurs in the decoding process between getting the
//  current sbploc, and updating it to have the appropriate 
//  significance values and significance levels)
// This method updates the neighborscoded data
//  of the coeffDats of coeffs that neighbor current sbpoc . 
//  it also increases currbitplane of the sbploc's currentdat
//   by one.. It then advances curr sbploc to the next sbploc
//  that will appear next, according to the defined sorting order. 
void SubbandIterator_updateAdvance(SubbandIterator *si);

// frees all memory allocated by InitAlloc, including heapnodes if present. 
void SubbandIterator_free(SubbandIterator *si); 

//order function #0: NULL
//order function #1:
int standard_order_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m);

// #2: reverse of standard order, except early bitplanes still come first. 
int reverse_standard_order_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m);

//#3:
int by_context_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m);
//#4:
int reverse_by_context_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m);
//#5:
int reverse_by_context_then_standard_order_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;
//#6:
int by_freq_of_context_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;
//#7:
int by_freq_of_context_then_standard_order_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;
//#8:
int by_issig_then_freq_of_context_then_standard_order_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;
//#9:
int JPEG2k_3_fractional_bitplanes_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;
//#10:
int by_JPEG2k_3_fractional_bitplanes_then_freq_and_standard_less_than(const CoeffHeapNode *x1, const CoeffHeapNode*x2, const QccENTArithmeticModel *m) ;


// call get_sorting_function with single int argument to get 
// one of the above function pointers. 
int (*get_sorting_function(int num))(const CoeffHeapNode *, const CoeffHeapNode *, const QccENTArithmeticModel *) ;

#endif /* SUBBANDITERATOR_H */
